package com.plugin; /**
 * 插件管理器的默认实现
 */
import java.io.*;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class DefaultPluginManager implements PluginManager {
    private final String pluginsDir;
    private final String cacheDir;
    private final List<Plugin> installedPlugins = new ArrayList<>();
    private final List<Plugin> runningPlugins = new ArrayList<>();
    private final List<PluginInfo> availablePlugins = new ArrayList<>();
    private final List<PluginListener> listeners = new ArrayList<>();
    
    public DefaultPluginManager(String pluginsDir, String cacheDir) {
        this.pluginsDir = pluginsDir;
        this.cacheDir = cacheDir;
        
        // 确保目录存在
        ResourceDirCreator.createSubprojectResourceDirs("PluginDemoV2", pluginsDir, cacheDir);

        // 加载已安装的插件
        loadInstalledPlugins();
        
        // 添加示例可用插件
        addSampleAvailablePlugins();
    }
    
    private void addSampleAvailablePlugins() {
        availablePlugins.add(new PluginInfo(
            "advanced-logger",
            "日志插件",
            "2.0.0",
            "提供增强的日志功能，包括彩色输出、文件记录和日志级别过滤",
                "PluginV2-1.0-SNAPSHOT.jar"
        ));
    }
    
    @Override
    public void downloadPlugin(String pluginPath) throws Exception {
        File targetFile = null;
        boolean isLocalFile = false;

        // 检查是否是URL还是本地文件路径
        if (pluginPath.startsWith("http://") || pluginPath.startsWith("https://") ||
                pluginPath.startsWith("ftp://")) {
            // 处理URL情况
            String fileName = pluginPath.substring(pluginPath.lastIndexOf('/') + 1);
            targetFile = new File(cacheDir, fileName);

            // 从URL下载文件
            try (InputStream in = new URL(pluginPath).openStream();
                 OutputStream out = Files.newOutputStream(targetFile.toPath())) {

                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
            }
        } else {
            // 处理本地文件路径情况
            File sourceFile = ResourceDirCreator.findResourcesFile("PluginDemoV2", pluginPath);
            if (sourceFile == null) {
                throw new FileNotFoundException("本地文件不存在: " + pluginPath);
            }
            // 验证文件是否存在
            if (!sourceFile.exists() || !sourceFile.isFile()) {
                throw new FileNotFoundException("本地文件不存在: " + pluginPath);
            }

            // 获取文件名
            String fileName = sourceFile.getName();
            Path resourcesPath = ResourceDirCreator.getResourcesPath("PluginDemoV2");
            if (resourcesPath == null) {
                System.err.println("找不到子项目PluginDemoV2的resources文件夹");
                return;
            }
            targetFile = resourcesPath.resolve(cacheDir).resolve(fileName).toFile();

            // 如果源文件不在缓存目录中，则复制文件到缓存目录
            if (!sourceFile.getParentFile().equals(cacheDir)) {
                Files.copy(sourceFile.toPath(), targetFile.toPath(),
                        StandardCopyOption.REPLACE_EXISTING);
            } else {
                // 源文件已经在缓存目录中，直接使用
                targetFile = sourceFile;
            }
            isLocalFile = true;
        }

        // 解析插件信息
        PluginInfo info = getPluginInfoFromJar(targetFile);
        if (info != null) {
            // 更新或添加到可用插件列表
            availablePlugins.removeIf(p -> p.getId().equals(info.getId()));
            availablePlugins.add(info);
        }

        // 触发事件，可以根据需要传递是否是本地文件的信息
        firePluginEvent(new PluginEvent(null, isLocalFile ?
                PluginEvent.Type.LOCAL_FILE_LOADED : PluginEvent.Type.DOWNLOADED));
    }
    
    @Override
    public void installPlugin(String pluginId) throws Exception {
        // 查找插件信息
        PluginInfo info = availablePlugins.stream()
            .filter(p -> p.getId().equals(pluginId))
            .findFirst()
            .orElseThrow(() -> new Exception("插件不存在: " + pluginId));
        
        // 查找缓存的JAR文件
        File jarFile = findPluginJarInCache(pluginId);
        if (jarFile == null || !jarFile.exists()) {
            throw new Exception("未找到插件缓存文件，需要先下载");
        }
        Path resourcesPath = ResourceDirCreator.getResourcesPath("PluginDemoV2");
        if (resourcesPath == null) {
            System.err.println("找不到子项目PluginDemoV2的resources文件夹");
            return;
        }
        // 复制到插件目录
        File destFile = resourcesPath.resolve(pluginsDir).resolve(jarFile.getName()).toFile();
        copyFile(jarFile, destFile);
        boolean delete = jarFile.delete();
        if (delete) {
            System.out.println("缓存中的文件已被删除");
        }
        // 加载插件
        Plugin plugin = loadPluginFromJar(destFile);
        if (plugin != null) {
            installedPlugins.add(plugin);
            firePluginEvent(new PluginEvent(plugin, PluginEvent.Type.INSTALLED));
        }
    }
    
    @Override
    public void uninstallPlugin(String pluginId) throws Exception {
        Plugin plugin = getPluginById(pluginId);
        if (plugin == null) {
            throw new Exception("插件未安装: " + pluginId);
        }
        
        // 如果插件正在运行，先停止
        if (isPluginRunning(pluginId)) {
            stopPlugin(pluginId);
        }
        
        // 从列表中移除
        installedPlugins.remove(plugin);
        
        // 删除插件文件
        File pluginFile = findPluginJarInPluginsDir(pluginId);
        if (pluginFile != null && pluginFile.exists()) {
            pluginFile.delete();
        }
        
        firePluginEvent(new PluginEvent(plugin, PluginEvent.Type.UNINSTALLED));
    }
    
    @Override
    public void startPlugin(String pluginId) throws Exception {
        Plugin plugin = getPluginById(pluginId);
        if (plugin == null) {
            throw new Exception("插件未安装: " + pluginId);
        }
        
        if (isPluginRunning(pluginId)) {
            throw new Exception("插件已在运行: " + pluginId);
        }
        
        // 启动插件
        plugin.start();
        runningPlugins.add(plugin);
        
        firePluginEvent(new PluginEvent(plugin, PluginEvent.Type.STARTED));
    }
    
    @Override
    public void stopPlugin(String pluginId) throws Exception {
        Plugin plugin = getPluginById(pluginId);
        if (plugin == null) {
            throw new Exception("插件未安装: " + pluginId);
        }
        
        if (!isPluginRunning(pluginId)) {
            throw new Exception("插件未在运行: " + pluginId);
        }
        
        // 停止插件
        plugin.stop();
        runningPlugins.remove(plugin);
        
        firePluginEvent(new PluginEvent(plugin, PluginEvent.Type.STOPPED));
    }
    
    @Override
    public List<Plugin> getInstalledPlugins() {
        return new ArrayList<>(installedPlugins);
    }
    
    @Override
    public List<PluginInfo> getAvailablePlugins() {
        return new ArrayList<>(availablePlugins);
    }
    
    @Override
    public Plugin getPluginById(String pluginId) {
        return installedPlugins.stream()
            .filter(p -> p.getId().equals(pluginId))
            .findFirst()
            .orElse(null);
    }
    
    @Override
    public boolean isPluginRunning(String pluginId) {
        return runningPlugins.stream()
            .anyMatch(p -> p.getId().equals(pluginId));
    }
    
    @Override
    public void addPluginListener(PluginListener listener) {
        listeners.add(listener);
    }
    
    @Override
    public void removePluginListener(PluginListener listener) {
        listeners.remove(listener);
    }
    
    /**
     * 加载已安装的插件
     */
    private void loadInstalledPlugins() {
        File dir = new File(pluginsDir);
        File[] jarFiles = dir.listFiles(f -> f.getName().endsWith(".jar"));
        
        if (jarFiles != null) {
            for (File jarFile : jarFiles) {
                try {
                    Plugin plugin = loadPluginFromJar(jarFile);
                    if (plugin != null) {
                        installedPlugins.add(plugin);
                    }
                } catch (Exception e) {
                    System.err.println("加载插件失败: " + jarFile.getName() + " - " + e.getMessage());
                }
            }
        }
    }
    
    /**
     * 从JAR文件加载插件
     */
    private Plugin loadPluginFromJar(File jarFile) throws Exception {
        try (URLClassLoader classLoader = new URLClassLoader(
                new URL[]{jarFile.toURI().toURL()},
                getClass().getClassLoader())) {
            
            // 查找实现了Plugin接口的类
            try (JarFile jar = new JarFile(jarFile)) {
                Enumeration<JarEntry> entries = jar.entries();
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    if (entry.getName().endsWith(".class") && !entry.isDirectory()) {
                        String className = entry.getName()
                                .replace("/", ".")
                                .replace(".class", "");
                        
                        try {
                            Class<?> clazz = classLoader.loadClass(className);
                            if (Plugin.class.isAssignableFrom(clazz) && !clazz.isInterface()) {
                                return (Plugin) clazz.getDeclaredConstructor().newInstance();
                            }
                        } catch (Exception e) {
                            // 忽略无法加载的类
                        }
                    }
                }
            }
        }
        
        return null;
    }
    
    /**
     * 从JAR文件获取插件信息
     */
    private PluginInfo getPluginInfoFromJar(File jarFile) {
        try {
            Plugin plugin = loadPluginFromJar(jarFile);
            if (plugin != null) {
                return new PluginInfo(
                    plugin.getId(),
                    plugin.getName(),
                    plugin.getVersion(),
                    plugin.getDescription(),
                    "本地缓存"
                );
            }
        } catch (Exception e) {
            System.err.println("获取插件信息失败: " + e.getMessage());
        }
        return null;
    }
    
    /**
     * 在缓存目录中查找插件JAR
     */
    private File findPluginJarInCache(String pluginId) {
        Path resourcesPath = ResourceDirCreator.getResourcesPath("PluginDemoV2");
        if (resourcesPath == null) {
            System.err.println("找不到子项目PluginDemoV2的resources文件夹");
            return null;
        }
        File dir = resourcesPath.resolve(cacheDir).toFile();
        File[] jarFiles = dir.listFiles(f -> f.getName().endsWith(".jar"));
        
        if (jarFiles != null) {
            for (File jarFile : jarFiles) {
                PluginInfo info = getPluginInfoFromJar(jarFile);
                if (info != null && info.getId().equals(pluginId)) {
                    return jarFile;
                }
            }
        }
        return null;
    }
    
    /**
     * 在插件目录中查找插件JAR
     */
    private File findPluginJarInPluginsDir(String pluginId) {
        Path resourcesPath = ResourceDirCreator.getResourcesPath("PluginDemoV2");
        if (resourcesPath == null) {
            System.err.println("找不到子项目PluginDemoV2的resources文件夹");
            return null;
        }
        File dir = resourcesPath.resolve(pluginsDir).toFile();
        File[] jarFiles = dir.listFiles(f -> f.getName().endsWith(".jar"));
        
        if (jarFiles != null) {
            for (File jarFile : jarFiles) {
                try {
                    PluginInfo info = getPluginInfoFromJar(jarFile);
                    if (info != null && info.getId().equals(pluginId)) {
                        return jarFile;
                    }
                } catch (Exception e) {
                    // 忽略错误
                }
            }
        }
        return null;
    }
    
    /**
     * 复制文件
     */
    private void copyFile(File source, File dest) throws IOException {
        try (InputStream in = new FileInputStream(source);
             OutputStream out = new FileOutputStream(dest)) {
            
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
    }
    
    /**
     * 触发插件事件
     */
    private void firePluginEvent(PluginEvent event) {
        for (PluginListener listener : new ArrayList<>(listeners)) {
            switch (event.getType()) {
                case INSTALLED:
                    listener.pluginInstalled(event);
                    break;
                case UNINSTALLED:
                    listener.pluginUninstalled(event);
                    break;
                case STARTED:
                    listener.pluginStarted(event);
                    break;
                case STOPPED:
                    listener.pluginStopped(event);
                    break;
                case DOWNLOADED:
                    listener.pluginDownloaded(event);
                    break;
            }
        }
    }
}
